package cn.com.generaldata.os.service.common;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import cn.com.generaldata.os.dao.intf.BaseDAOInterface;
import cn.com.generaldata.os.newpojo.ReportType;
import cn.com.generaldata.os.newpojo.ReportVersion;
import cn.com.generaldata.os.pojo.DustryReport;
import cn.com.generaldata.os.pojo.Industry;
import cn.com.generaldata.os.pojo.ReportTypeItem;

@Component
public class ReportTypeService {

	@Autowired
	@Qualifier("baseDAO")
	private BaseDAOInterface<ReportType> reportTypeDAO;

	@Autowired
	@Qualifier("baseDAO")
	private BaseDAOInterface<ReportTypeItem> reportTypeItemDAO;

	@Autowired
	@Qualifier("baseDAO")
	private BaseDAOInterface<DustryReport> dustryReportDAO;


	public ReportType getReportTypeById(String id) {
		return reportTypeDAO.get(ReportType.class, id);
	}


	public List<ReportType> getReportTypeList(String versionId) {
		String hql = "from ReportType where versionId = ? order by typeCode";
		return reportTypeDAO.findByHql(hql, Integer.valueOf(versionId));
	}

	/**
	 * 添加报表类型.
	 */

	public void addReportType(ReportType newType) {
		if (newType.getId() == null || "".equals(newType.getId()))
			newType.setId(UUID.randomUUID().toString().replaceAll("-", ""));
		reportTypeDAO.save(newType);
	}

	/**
	 * 更新报表类型.
	 */

	public void updateReportType(ReportType targetType) {
		reportTypeDAO.update(targetType);
	}

	/**
	 * 添加报表类型项目.
	 */
	
	public void addReportTypeItem(ReportTypeItem newTypeItem) {
		if(newTypeItem.getId()==null || "".equals(newTypeItem.getId()))
			newTypeItem.setId(UUID.randomUUID().toString().replaceAll("-", ""));
		reportTypeItemDAO.save(newTypeItem);

	}

	/**
	 * 删除报表类型项目.
	 */
	
	public void deleteReportTypeItem(ReportTypeItem targetTypeItem) {
		reportTypeItemDAO.delete(targetTypeItem);

	}

	/**
	 * 取得报表类型项目的列表.
	 */
	
	public List<ReportTypeItem> getReportTypeItemList(String typeId) {
		String hql = "from ReportTypeItem where reportTypeId = ? order by itemRow,itemCell";
		return reportTypeItemDAO.findByHql(hql, typeId);
	}

	/**
	 * 更新报表类型项目.
	 */
	
	public void updateReportTypeItem(ReportTypeItem targetTypeItem) {
		reportTypeItemDAO.update(targetTypeItem);

	}

	/**
	 * 检查项目Key是否已经存在.
	 */
	
	public boolean isItemKeyExist(String versionId, String itemKey) {

		List<ReportType> reportTypeList = getReportTypeList(versionId);
		String[] rtIds = new String[reportTypeList.size()];
		for (int i = 0; i < reportTypeList.size(); i++) {
			rtIds[i] = reportTypeList.get(i).getId();
		}
		String hql = "from ReportTypeItem where reportTypeId in ? and itemKey = ?";
		List<ReportTypeItem> list = reportTypeItemDAO.findByHql(hql, rtIds, itemKey);
		return list.size() > 0;
	}

	/**
	 * 检查报表Code是否已存在.
	 */

	public boolean isTypeCodeExist(String versionId, String typeCode) {
		String hql = "from ReportType where versionId = ? and typeCode = ?";
		List<ReportType> list = reportTypeDAO.findByHql(hql, Integer.valueOf(versionId), typeCode);
		return list.size() > 0;
	}

	/**
	 * 取得指定版本下，已经与行业关联的报表类型的列表.
	 */

	public List<ReportType> getReportTypeListByVerAndInd(String versionId, String industryId) {
		String sql = "from DustryReport where industry.id=?";
		List<DustryReport> linkList = dustryReportDAO.findByHql(sql, industryId);
		String[] rtIds = new String[linkList.size()];
		for (int i = 0; i < linkList.size(); i++) {
			rtIds[i] = linkList.get(i).getReportTypeId();
		}
		String hql = "from ReportType where versionId = ? and id in ? order by typeCode";
		return reportTypeDAO.findByHql(hql, Integer.valueOf(versionId), rtIds);
	}

	/**
	 * 保存行业与报表类型的关联.
	 */

	public void saveIndLinkedReportType(String versionId, String industryId, String typeIdJoinStr) {

		String hql = "from ReportType where versionId = ?";
		List<ReportType> list = reportTypeDAO.findByHql(hql, Integer.valueOf(versionId));
		String[] rtIds = new String[list.size()];
		for (int i = 0; i < list.size(); i++) {
			rtIds[i] = list.get(i).getId();
		}
		String sql = "from DustryReport where industry.id=? and reportTypeId in ?";
		List<DustryReport> oldList = dustryReportDAO.findByHql(sql, industryId, rtIds);

		// 删除旧的关联
		// String hql =
		// "select L from ReportType T inner join T.dustryReports L where T.version.id = ? and L.industry.id=?";
		// List<DustryReport> oldList = dustryReportDAO.findByHql(hql, versionId, industryId);
		dustryReportDAO.delete(oldList);

		// 创建新的关联
		if (typeIdJoinStr.length() > 0) {
			String[] typeIdArray = typeIdJoinStr.split(",");
			for (String typeId : typeIdArray) {

				// 行业
				Industry industry = new Industry();
				industry.setId(industryId);

				// 报表类型
				// ReportType reportType = new ReportType();
				// reportType.setId(typeId);

				// 关联
				DustryReport newLink = new DustryReport();
				newLink.setIndustry(industry);
				newLink.setReportTypeId(typeId);
				newLink.setId(UUID.randomUUID().toString().replaceAll("-", ""));
				dustryReportDAO.save(newLink);
			}
		}

	}


	public void deleteReportType(ReportType targetType) {

		// ReportType对象传到客户端，并没有带集合属性过去，所以需要重新取得。
		String hql = "from DustryReport where reportTypeId = ?";
		List<DustryReport> linkList = dustryReportDAO.findByHql(hql, targetType.getId());

		// 删除行业关联
		for (DustryReport item : linkList) {
			dustryReportDAO.delete(item);
		}

		// ReportType对象传到客户端，并没有带集合属性过去，所以需要重新取得。
		hql = "from ReportTypeItem where reportTypeId = ?";
		List<ReportTypeItem> itemList = reportTypeItemDAO.findByHql(hql, targetType.getId());

		// 删除报表项目
		for (ReportTypeItem item : itemList) {
			reportTypeItemDAO.delete(item);
		}

		// 删除报表类型
		reportTypeDAO.delete(targetType);
	}



	/**
	 * 上传报表类型模板文件.
	 */
	
	public String uploadReportTypeFile(String versionId, String fileName, byte[] fileData, boolean autoCreateItemFlag) {
		FileOutputStream os = null;
		try {
			// 原名，保存到reports目录下
			String webRootPath = new ClassPathResource("/").getFile().getParentFile().getParentFile().getAbsolutePath();
			String savePath = webRootPath + File.separator + "reports" + File.separator + fileName;

			// 写入字节流
			os = new FileOutputStream(new File(savePath));
			os.write(fileData, 0, fileData.length);
			os.close();

			// report_s104_100.xml是版本1的，_200是版本2的，_1000是版本10的文件
			// 根据XML文件导入Item数据
			if (autoCreateItemFlag) {
				Pattern p = Pattern.compile("^report_([sS]\\d{1,3}).*xml$");
				Matcher m = p.matcher(fileName);
				if (m.matches()) {
					importItemData(versionId, m.group(1), new String(fileData, "UTF-8"));
				}
			}

			return "OK";
		} catch (IOException e) {
			return e.getMessage();
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
				}
			}
		}
	}

	/**
	 * 根据XML自动生成Item记录.
	 * 
	 * @param versionId
	 *            版本ID
	 * @param typeCode
	 *            报表类型Code
	 * @param fileContent
	 *            XML文件内容
	 *            @
	 */
	private void importItemData(String versionId, String typeCode, String fileContent) {
		if (fileContent.length() < 100) {
			return;
		}

		// 取得报表类型
		String hql = "from ReportType where versionId = ? and typeCode = ?";
		List<ReportType> typeList = reportTypeDAO.findByHql(hql, Integer.valueOf(versionId), typeCode.toUpperCase());
		if (typeList.size() == 0) {
			return;
		}
		ReportType belongType = typeList.get(0);

		// <Row>
		// <rowId>1</rowId>
		// <rowType>12</rowType>
		// <groupNo>NULL</groupNo>
		// <rowIndex>001</rowIndex>
		// <F1>功能区增加值</F1>
		// <F2>万元</F2>
		// <F3>01</F3>
		// <F4 key="1805"></F4>
		// <F5 key="1817"></F5>
		// <F6 key="1829"></F6>
		// <F7 key="1841"></F7>
		// </Row>

		// 分析文件内容
		Pattern p = Pattern.compile("<Row>(.*?)</Row>", Pattern.DOTALL);
		Matcher m = p.matcher(fileContent);
		while (m.find()) {
			String rowContent = m.group(0);

			// <rowIndex>001</rowIndex>
			Pattern p2 = Pattern.compile("<rowIndex>(.*?)</rowIndex>", Pattern.DOTALL);
			Matcher m2 = p2.matcher(rowContent);
			if (!m2.find()) {
				continue;
			}
			String row = m2.group(1);

			// <F1>国内旅游人次数</F1>
			// <F4 key="xxxx">国内旅游人次数</F4>
			Pattern p3 = Pattern.compile("<(F\\d{1,3})(?:\\s+key=[\"'](.*?)[\"'])?>(.*?)</F\\d{1,3}>", Pattern.DOTALL);
			Matcher m3 = p3.matcher(rowContent);
			String F1 = ""; // 记住F1名字，拼Key用
			int count = 1; // 输入项目计数
			while (m3.find()) {
				String cell = m3.group(1);
				String key = m3.group(2); // 无key该值是null
				String name = m3.group(3);
				if (cell.equals("F1")) {
					F1 = name;
				}

				// 保存到DB
				ReportTypeItem newItem = new ReportTypeItem();
				newItem.setReportTypeId(belongType.getId());
				if (name.trim().length() > 0) {
					newItem.setItemType((short) 0); // 0是Label、1是TextBox
				} else {
					newItem.setItemType((short) 1);
				}
				newItem.setItemRow(row);
				newItem.setItemCell(cell); // F1

				if (name.trim().length() > 0) {
					newItem.setItemKey(""); // Label无需Key
					newItem.setItemName(name.trim()); // 国内旅游人次数
				} else {
					// 有Key用Key，没Key拼Key
					if (key != null && key.length() > 0) {
						newItem.setItemKey(key);
						newItem.setItemName(key);
					} else {
						newItem.setItemKey(F1 + "_Input_" + count);
						newItem.setItemName(F1 + "_Input_" + count);
						count++;
					}
				}
				reportTypeItemDAO.save(newItem);
			}
		}
	}
	
	/**
	 * 从指定版本下，导入选择的报表类型及表格项目和行业关联.
	 */
	
	public void importReportType(String versionId, String typeIdJoinStr) {

		if (typeIdJoinStr.length() == 0) {
			return;
		}

		String[] typeIdArray = typeIdJoinStr.split(",");
		for (String typeId : typeIdArray) {

			// 检索复制源
			String hql = "from ReportType where id = ?";
			List<ReportType> list = reportTypeDAO.findByHql(hql, typeId);
			if (list.size() == 0) {
				continue;
			}

			// 检查报表Code在当前版本中是否已经存在
			ReportType from = list.get(0);
			if (isTypeCodeExist(versionId, from.getTypeCode())) {
				continue;
			}
			String sql = "from DustryReport where reportTypeId= ?";
			List<DustryReport> linkArray = dustryReportDAO.findByHql(sql, from.getId());
			String sql2 = "from ReportTypeItem where reportTypeId= ?";
			List<ReportTypeItem> itemArray = reportTypeItemDAO.findByHql(sql2, from.getId());

			// Set<DustryReport> linkArray = from.getDustryReports();
			// Set<ReportTypeItem> itemArray = from.getTypeItems();

			// 设置并保存报表类型
			ReportType to = new ReportType();
			BeanUtils.copyProperties(from, to); // 对象属性也复制了。

			// 更换属性
			ReportVersion v = new ReportVersion();
			v.setId(Integer.valueOf(versionId));
			to.setVersionId(Integer.valueOf(versionId));
			// to.setDustryReports(null);
			// to.setTypeItems(null);
			to.setId(null);
			reportTypeDAO.save(to);

			// 行业关联
			for (DustryReport link : linkArray) {
				DustryReport newLink = new DustryReport();
				newLink.setIndustry(link.getIndustry());
				newLink.setReportTypeId(to.getId());
				dustryReportDAO.save(newLink);
			}

			// 报表项目
			for (ReportTypeItem item : itemArray) {
				ReportTypeItem newItem = new ReportTypeItem();
				BeanUtils.copyProperties(item, newItem); // 复制属性
				newItem.setId(null);
				newItem.setReportTypeId(to.getId());
				reportTypeItemDAO.save(newItem);
			}
		}
	}

}
